<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>简单排序</title>
  </head>
  <body>
    <p style="display: inline-block">请输入一个表达式:</p>
    <input type="text" />
    <span></span>
    <script>
      function infixToSuffix(infix) {
        let symbol = [],
          value = [],
          res = "";
        infix.split("").forEach((item) => {
          switch (true) {
            case /\d/.test(item):
              value.push(item);
              break;
            case /[+\-*/]/.test(item):
              while (symbol.length + 1) {
                if (
                  !symbol.length ||
                  !/[+\-*/]/.test(symbol[symbol.length - 1])
                ) {
                  // 栈顶为空或非运算符
                  symbol.push(item); // 弹入栈1
                  break;
                }
                if (
                  /[*/]/.test(item) &&
                  /[+\-]/.test(symbol[symbol.length - 1])
                ) {
                  // 比栈顶低
                  symbol.push(item); // 弹入栈1
                  break;
                }
                if (
                  /[+\-]/.test(item) &&
                  /[*/]/.test(symbol[symbol.length - 1])
                ) {
                  // 比栈顶高
                  value.push(symbol.pop()); // 弹出栈顶，栈顶弹入栈2
                  continue;
                }
                // 等于栈顶
                value.push(item); // 弹入栈2
                break;
              }
              break;
            case /\(/.test(item):
              symbol.push(item);
              break;
            case /\)/.test(item):
              while (symbol.length) {
                let mid = symbol.pop();
                if (mid !== "(") {
                  value.push(mid);
                } else break;
              }
              break;
            default:
          }
        });
        while (value.length) {
          symbol.push(value.pop());
        }
        while (symbol.length) {
          res += symbol.pop();
        }
        return res;
      }
      function evalRPN(tokens) {
        const operation = {
          "+": (a, b) => a + b,
          "-": (a, b) => a - b,
          "*": (a, b) => a * b,
          "/": (a, b) => {
            if (b < 0) {
              return 0;
            } else {
              return parseInt(a / b);
            }
          },
        };
        const stack = [];
        for (let i = 0; i < tokens.length; i++) {
          if (tokens[i] in operation) {
            if (stack.length >= 2) {
              const b = Number(stack.pop());
              const a = Number(stack.pop());
              const result = operation[tokens[i]](a, b);
              stack.push(result);
            } else {
              return 0;
            }
          } else {
            stack.push(tokens[i]);
          }
        }
        return stack.pop();
      }
      console.log(evalRPN(infixToSuffix("1+2*3+(4*5+6)*7")));
      console.log(infixToSuffix("99+10"));
      console.log(infixToSuffix("(3+4)*5-6")); // 34+5*6-
      console.log(infixToSuffix("1+2*3+(4*5+6)*7")); // 123*+45*6+7*+

      // 正则匹配数学公式
      (function () {
        /*
         * 假如待选变量：  ID,NUM,TOTAL，AVL TEST
         * 正确的公式例子：ID*NUM+(TOTAL/AVL)*0.5
         * 错误的公式例子：ID**|0.5
         */

        function fn(string, obj) {
          // TODO: 如何处理=？
          // 剔除空白符
          string = string.replace(/\s/g, "");

          // 错误情况，空字符串
          if ("" === string) {
            return false;
          }

          // 错误情况，运算符连续
          if (/[\+\-\*\/]{2,}/.test(string)) {
            return false;
          }

          // 空括号
          if (/\(\)/.test(string)) {
            return false;
          }

          // 错误情况，括号不配对
          var stack = [];
          for (var i = 0, item; i < string.length; i++) {
            item = string.charAt(i);
            if ("(" === item) {
              stack.push("(");
            } else if (")" === item) {
              if (stack.length > 0) {
                stack.pop();
              } else {
                return false;
              }
            }
          }
          if (0 !== stack.length) {
            return false;
          }

          // 错误情况，(后面是运算符
          if (/\([\+\-\*\/]/.test(string)) {
            return false;
          }

          // 错误情况，)前面是运算符
          if (/[\+\-\*\/]\)/.test(string)) {
            return false;
          }

          // 错误情况，(前面不是运算符
          if (/[^\+\-\*\/]\(/.test(string)) {
            return false;
          }

          // 错误情况，)后面不是运算符
          if (/\)[^\+\-\*\/]/.test(string)) {
            return false;
          }
          //错误情况，使用除()+-*/之外的字符
          if (/[^\+\-\*\/0-9.a-zA-Z\(\)]/.test(string)) {
            return false;
          }

          //运算符号不能在首末位
          if (/^[\+\-\*\/.]|[\+\-\*\/.]$/.test(string)) {
            return false;
          }

          // 错误情况运算符结尾
          if (/[\+\-\*\/]$/.test(string)) {
            console.error("运算符结尾");
            return false;
          }

          // 错误情况，变量没有来自“待选公式变量”
          var tmpStr = string.replace(/[\(\)\+\-\*\/]{1,}/g, "`");
          var array = tmpStr.split("`");
          for (var i = 0, item; i < array.length; i++) {
            item = array[i];
            console.log(item);
            if (/[A-Z]/i.test(item) && "undefined" === typeof obj[item]) {
              return false;
            }
          }

          return true;
        }

        // 测试
        var fields = {
          ID: 1,
          TOTAL: 1,
          AVL: 1,
          NUM: 1,
          "高":3,
          "度高":5
        };
        // 提交到服务器端的字符串不应该包含空白符，或者应该禁止用户输入空白符
        alert(fn("ID*NUM+(TOTAL/AVL)*0.5", fields));
      })();

      var str = "1,2,3,4,5";
      var reg = {
        管理员: 1,
        2: "会员",
        3: "超级会员",
        4: "超级管理员",
        5: "终极用户",
      };
      for (var n in reg) {
        str = str.replace(new RegExp(n, "ig"), reg[n]);
      }
      alert(str);

      // demo
      let suffixExpression = infixToSuffix("99+(1-2)");
      let list = suffixExpression.split("");
      console.log(list);
      //创建栈，只需要一个栈即可
      let stack = [];
      for (let item of list) {
        if (item.match(/\d+/)) {
          //匹配是多位数
          //入栈
          stack.push(item);
        } else {
          //pop出两个数，并运算，再入栈
          let num2 = parseInt(stack.pop());
          let num1 = parseInt(stack.pop());
          let res = 0;
          if (item === "+") {
            res = num1 + num2;
          } else if (item === "-") {
            console.log(111);
            res = num1 - num2;
          } else if (item === "*") {
            res = num1 * num2;
          } else if (item === "/") {
            res = num1 / num2;
          } else {
            throw new Error("运算符有误");
          }
          //把res入栈
          stack.push(res + "");
        }
      }
      //最后留在stack中的数据就是运算结果
      console.log(suffixExpression + "的计算的结果是：", stack.pop());

      class Stack {
        constructor() {
          this._items = []; // 储存数据
        }
        // 向栈内压入一个元素
        push(item) {
          this._items.push(item);
        }
        // 把栈顶元素弹出
        pop() {
          return this._items.pop();
        }
        // 返回栈顶元素
        peek() {
          return this._items[this._items.length - 1];
        }
        // 判断栈是否为空
        isEmpty() {
          return !this._items.length;
        }
        // 栈元素个数
        size() {
          return this._items.length;
        }
        // 清空栈
        clear() {
          this._items = [];
        }
      }

      // 将普通算数表达式即中缀表达式转换为逆波兰表达式即后缀表达式
      function rp(str) {
        var arr = str.split(" ");
        var ops = "+-#*/".split(""); // #用来分级，+-是同一级，*/同一级，两级之间的位置差至少为2
        var result = [],
          temp = [];
        arr.forEach(function (ele, ind) {
          if (ele == "(") {
            temp.push(ele); // 左括号直接推入暂存区
          } else if (ele == ")") {
            var flag = true;
            while (flag) {
              if (temp[temp.length - 1] != "(") {
                result.push(temp.pop());
              } else {
                temp.pop();
                flag = false;
              }
            }
          } else if (ops.indexOf(ele) != -1) {
            cb(ele, temp);
            function cb(x, o) {
              if (
                o.length == 0 ||
                o[o.length - 1] == "(" ||
                ops.indexOf(x) - ops.indexOf(o[o.length - 1]) > 2
              ) {
                //判断分级
                o.push(x);
              } else {
                result.push(o.pop());
                return cb(x, o);
              }
            }
          } else {
            result.push(ele);
          }
        });
        while (temp.length > 0) {
          if (temp[temp.length - 1] != "(") {
            result.push(temp.pop());
          } else {
            temp.pop();
          }
        }
        console.log(result);
        return result;
      }

      function isOperator(str) {
        return ["+", "-", "*", "/"].includes(str);
      }
      // 逆波兰表达式计算
      function clacExp(exp) {
        const stack = new Stack();
        for (let i = 0; i < exp.length; i++) {
          const one = exp[i];
          if (isOperator(one)) {
            const operatNum1 = stack.pop();
            const operatNum2 = stack.pop();
            const expStr = `${operatNum2}${one}${operatNum1}`;
            const res = eval(expStr);
            stack.push(res);
          } else {
            stack.push(one);
          }
        }
        return stack.peek();
      }
      console.log(rp("99 + 10 + -5"));
      console.log(clacExp(rp("99 + 10 + -5")));

      var s = "共分为30期+60";
      var m = s.match(/\d+/);
      console.log(m);
      if (m) {
        alert(m[0]);
      }
    </script>
  </body>
</html>
